﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Web.Mvc;
using ControleRepresentante.Logic.Models;
using ControleRepresentante.Logic.Repositories;
using ControleRepresentante.Logic.Statistics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WebSite.Controllers;
using WebSite.ViewModels.EditViewModels;

namespace ControleRepresentante.UnitTests
{
    public static class TestScenarioPedidoHelper
    {
        public static void DeletePedido(this TestScenario testScenario, Guid pedidoId)
        {
            IPedidoRepository pedidoRepository = testScenario.RepositoryProvider.GetRepository<IPedidoRepository>(testScenario.ImpostProvider);
            PedidoStatistics statistics;
            int countBefore = pedidoRepository.GetModels(out statistics).Count();
            using (PedidoController pedidoController = new PedidoController(testScenario.RepositoryProvider, testScenario.SessionConfiguration, testScenario.ControllerExtensionProvider, testScenario.PrintTemplateSelector, testScenario.ImpostProvider))
            {
                pedidoController.Delete(pedidoId);
                pedidoController.Delete(pedidoId, null);
                Assert.AreEqual(countBefore - 1, pedidoRepository.GetModels(out statistics).Count());
            }
        }

        public static Guid CreatePedido(this TestScenario testScenario, Pedido pedido)
        {
            IPedidoRepository pedidoRepository = testScenario.RepositoryProvider.GetRepository<IPedidoRepository>(testScenario.ImpostProvider);
            PedidoStatistics statistics;
            int countBefore = pedidoRepository.GetModels(out statistics).Count();
            using (PedidoController pedidoController = new PedidoController(testScenario.RepositoryProvider, testScenario.SessionConfiguration, testScenario.ControllerExtensionProvider, testScenario.PrintTemplateSelector, testScenario.ImpostProvider))
            {
                ActionResult actionResult = pedidoController.Create();
                ViewResult viewResult = (ViewResult)actionResult;
                Assert.IsInstanceOfType(viewResult.Model, typeof(PedidoEditViewModel));
                PedidoEditViewModel pedidoEditViewModel = (PedidoEditViewModel)viewResult.Model;
                Assert.IsNull(pedidoEditViewModel.Message);

                foreach (Produto produto in pedido.Produtos)
                {
                    pedidoController.ProdutoInsert(produto.Quantidade, produto.Codigo, produto.Descricao, produto.PrecoUnitario);
                }
                NameValueCollection collection = new NameValueCollection();
                foreach (AttributeValue attributeValue in pedido.AttributeValues)
                {
                    collection.Add("_" + attributeValue.Attribute.Name, attributeValue.Value);
                }
                FormCollection formCollection = new FormCollection(collection);
                actionResult = pedidoController.Create(pedido.Cliente.Id, pedido.Vendedor.Id,
                                                                    pedido.Fabrica.Id, pedido.Transportadora.Id,
                                                                    pedido.Data, pedido.CondicaoPagamento,
                                                                    pedido.PrazoEntrega, pedido.Observacao,
                                                                    pedido.Desconto, pedido.Faturado, pedido.Cancelado, formCollection);
                IEnumerable<Pedido> pedidos = pedidoRepository.GetModels(out statistics);
                Assert.AreEqual(countBefore + 1, pedidos.Count());
                Pedido addedPedido = pedidos.FirstOrDefault(x => x.PrazoEntrega == pedido.PrazoEntrega);
                Assert.AreEqual(pedido.Cliente.Id, addedPedido.Cliente.Id);
                Assert.AreEqual(pedido.CondicaoPagamento, addedPedido.CondicaoPagamento);
                Assert.AreEqual(pedido.Data, addedPedido.Data);
                Assert.AreEqual(pedido.Desconto, addedPedido.Desconto);
                Assert.AreEqual(pedido.Fabrica.Id, addedPedido.Fabrica.Id);
                Assert.AreEqual(pedido.Observacao, addedPedido.Observacao);
                Assert.AreEqual(pedido.PrazoEntrega, addedPedido.PrazoEntrega);
                Assert.AreEqual(pedido.Faturado, addedPedido.Faturado);
                Assert.AreEqual(pedido.Cancelado, addedPedido.Cancelado);
                Assert.AreEqual(pedido.Transportadora.Id, addedPedido.Transportadora.Id);
                Assert.AreEqual(pedido.Vendedor.Id, addedPedido.Vendedor.Id);

                Assert.AreEqual(pedido.Produtos.Count(), addedPedido.Produtos.Count());
                foreach (Produto produto in pedido.Produtos)
                {
                    Produto addedProduto = addedPedido.Produtos.SingleOrDefault(x => x.Descricao == produto.Descricao);
                    Assert.AreEqual(produto.Codigo, addedProduto.Codigo);
                    Assert.AreEqual(produto.PrecoUnitario, addedProduto.PrecoUnitario);
                    Assert.AreEqual(produto.Quantidade, addedProduto.Quantidade);
                }

                Assert.IsInstanceOfType(actionResult, typeof(RedirectToRouteResult));
                RedirectToRouteResult redirectToRouteResult = (RedirectToRouteResult)actionResult;
                Assert.AreEqual("Details", redirectToRouteResult.RouteValues["action"]);
                Assert.AreEqual(addedPedido.Id, redirectToRouteResult.RouteValues["id"]);
                return addedPedido.Id;
            }
        }

        public static void AddPost(this TestScenario testScenario, Guid pedidoId, string comentario)
        {
            IPedidoRepository pedidoRepository = testScenario.RepositoryProvider.GetRepository<IPedidoRepository>(testScenario.ImpostProvider);
            int countBefore = pedidoRepository.GetModelById(pedidoId).Posts.Count();

            using (PedidoController pedidoController = new PedidoController(testScenario.RepositoryProvider, testScenario.SessionConfiguration, testScenario.ControllerExtensionProvider, testScenario.PrintTemplateSelector, testScenario.ImpostProvider))
            {
                ActionResult actionResult = pedidoController.AddPost(pedidoId, comentario);
                Assert.IsInstanceOfType(actionResult, typeof(RedirectToRouteResult));
                RedirectToRouteResult redirectToRouteResult = (RedirectToRouteResult) actionResult;
                Assert.AreEqual("Details", redirectToRouteResult.RouteValues["action"]);
                Assert.AreEqual(pedidoId, redirectToRouteResult.RouteValues["id"]);
                IEnumerable<Post> posts = pedidoRepository.GetModelById(pedidoId).Posts;
                Assert.AreEqual(countBefore + 1, posts.Count());
                Post post = posts.Single(x => x.Comentario == comentario);
                Assert.AreEqual(pedidoRepository.User, post.User);
            }
        }

        internal static Guid CreatePedido(this TestScenario testscenario, Guid vendedorId, Guid clienteId, Guid transportadoraId, Guid fabricaId)
        {
            Pedido pedido = new Pedido
            {
                Vendedor = new Vendedor {Id = vendedorId},
                Cliente = new Cliente {Id = clienteId},
                Transportadora = new Transportadora {Id = transportadoraId},
                Fabrica = new Fabrica {Id = fabricaId}
            };
            return testscenario.CreatePedido(pedido);
        }
    }
}
